﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;
using System.Collections.Specialized;
using System.Collections;

namespace Pariveda.DataAccess35.Business

{
    /// <summary>
    /// Service Layer for Managing Customers
    /// </summary>
    public class CustomerService
    {
        /// <summary>
        /// Gets the lookup list for customers
        /// </summary>
        /// <returns></returns>
        public List<KeyValuePair<int, string>> GetLookupList()
        {
            using (AdventureWorksDataContext db = new AdventureWorksDataContext())
            {
                var customers = from c in db.Customers
                                orderby c.CompanyName
                                select new KeyValuePair<int, string>(c.CustomerID, c.CompanyName);
                return customers.ToList();
            }
        }

        /// <summary>
        /// Gets the specified customer 
        /// </summary>
        /// <param name="customerId">The id of the customer to get</param>
        /// <param name="getAddresses">if set to <c>true</c> also include the child addresses.</param>
        /// <returns></returns>
        public Customer Get(int customerId, bool getAddresses)
        {
            using (AdventureWorksDataContext db = new AdventureWorksDataContext())
            {
                GetFullCustomerGraph(db);
                return db.Customers.SingleOrDefault(c => c.CustomerID == customerId);
            }
        }

        /// <summary>
        /// Searches for the customer by company name
        /// </summary>
        /// <param name="companyName">Name of the company.</param>
        /// <returns></returns>
        public List<Customer> SearchByCompanyName(string companyName)
        {
            using (AdventureWorksDataContext db = new AdventureWorksDataContext())
            {
                GetFullCustomerGraph(db);
                var customers = from c in db.Customers
                                where c.CompanyName.StartsWith(companyName)
                                select c;
                return customers.ToList();
            }
        }

        /// <summary>
        /// Updates the specified customer.
        /// </summary>
        /// <param name="customer">The customer to update.</param>
        public Customer Update(Customer customer)
        {
            using (AdventureWorksDataContext db = new AdventureWorksDataContext())
            {
                if (customer.CustomerID > 0)
                {
                    db.Customers.Attach(customer, true);

                    var deletedAddresses = from ca in db.CustomerAddresses
                                           where !(from a in customer.CustomerAddresses select a.AddressID).Contains(ca.AddressID)
                                           && ca.CustomerID == customer.CustomerID
                                           select ca;
                    db.CustomerAddresses.DeleteAllOnSubmit(deletedAddresses);
                    db.CustomerAddresses.InsertAllOnSubmit(
                        from a in customer.CustomerAddresses
                        where a.AddressID == 0
                        select a);
                    foreach (CustomerAddress address in
                        from a in customer.CustomerAddresses
                        where a.AddressID > 0
                        select a)
                    {
                        db.CustomerAddresses.Attach(address, true);
                    }
                }
                else
                {
                    db.Customers.InsertOnSubmit(customer);
                    //db.CustomerAddresses.InsertAllOnSubmit(customer.CustomerAddresses);
                }
                db.SubmitChanges();
                return customer;
            }
        }

        /// <summary>
        /// Deletes the customer specified by customer id.
        /// </summary>
        /// <param name="customerId">The customer id.</param>
        public void Delete(int customerId)
        {
            using (AdventureWorksDataContext db = new AdventureWorksDataContext())
            {
                Customer customer = db.Customers.SingleOrDefault(c => c.CustomerID == customerId);
                if (customer != null)
                {
                    db.CustomerAddresses.DeleteAllOnSubmit(customer.CustomerAddresses);
                    db.Customers.DeleteOnSubmit(customer);
                    db.SubmitChanges();
                }
            }
        }

        /// <summary>
        /// Deletes the customers specified by the customer ids.
        /// </summary>
        /// <param name="customerIds">The customer ids.</param>
        public void Delete(IEnumerable<int> customerIds)
        {
            foreach (int customerId in customerIds)
            {
                Delete(customerId);
            }
        }

        /// <summary>
        /// Sets the load options to enable full object graph gets.
        /// </summary>
        /// <param name="db">The db to apply the options t</param>
        void GetFullCustomerGraph(AdventureWorksDataContext db)
        {
            DataLoadOptions options = new DataLoadOptions();
            options.LoadWith<Customer>(c => c.CustomerAddresses);
            db.LoadOptions = options;
        }
    }
}
